#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define FILE_NAME "log.txt"

int main()
{
    //char buffer[1024];
    //ssize_t s = read(0, buffer, 1024);//从buffer中读取1024个字节，read返回值为读取的字节数
    //if(s > 0)//说明读取到了内容，也说明了系统确实默认打开fd = 0，1，2的文件，而不需要用户自己打开
    //{
    //    buffer[s-1] = 0;//不要最后输入的回车键被打印，所以减1
    //    //printf("echo# %s\n", buffer);
    //    write(1, buffer, strlen(buffer)); //向fd=1（显示器）写入buffer的内容（注意无需写入字符串最后的斜杠零）
    //}

    
    ////close(1);//这句代码会关闭fd=1的显示器，所以运行之后无法在显示器打印任何内容，但是下面文件的fd确实是1
    //close(0);//此时下面的fd=0，如果是close（2），那么下面的fd=2
    //////也就是说文件描述符的分配规则是寻找最小的、没有被使用的数组下标分配给指定的文件
    //int fd = open(FILE_NAME, O_RDONLY);//以只读的方式打开
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    //char buffer[1024];//定义一个文件缓冲区
    //fread(buffer, 1, sizeof(buffer), stdin); // stdin->fd: 0 -- 输入重定向（本来从键盘输入，现在变成从文件输入）
    //printf("%s\n", buffer);
    //close(fd);

    //close(1);//这句代码会关闭fd=1的显示器，所以运行之后无法在显示器打印任何内容
    //int fd = open(FILE_NAME, O_CREAT|O_WRONLY|O_APPEND, 0666);//文件不存在就创建文件|以写的方式打开|每次都是追加
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    ////printf("fd: %d\n",fd);//这两句代码的内容都无法在显示器打印，但是打印的内容却写到了log.txt中，这就是输出重定向
    ////printf("stdout->fd: %d\n",stdout->_fileno);//printf打印只认stdout中的fileno=1，而上面的clsoe（1）使得log.txt的fd=1
    //////所以printf转而向该文件写内容，重定向的本质就是修改特定文件描述符表中的数组的内容（上面下标为1的位置填的内容是log.txt的地址）
    //////fprintf就是比printf多了第一个参数file stream，能够指定向哪个文件打印
    //fprintf(stdout, "fd: %d\n", fd);//同上，stdout的fileno一直为1，而此时log.txt的fd=1，所以还是向该文件追加
    //fprintf(stdout, "stdout->fd: %d\n", stdout->_fileno);//追加重定向，每次运行myfile都会追加一次
    //fflush(stdout);//不加这句代码就无法在文件log.txt中看到打印的信息
    //close(fd);


    //int fd = open(FILE_NAME, O_WRONLY | O_CREAT | O_APPEND, 0666);
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    //dup2(fd, 1);//将fd对应的内容覆盖下标为1的位置对应的内容，输出重定向到log.txt
    //printf("hello printf\n");
    //fprintf(stdout, "hello fprintf\n");
    //close(fd);

    //int fd = open(FILE_NAME, O_RDONLY);
    //if(fd < 0)
    //{
    //    perror("open");
    //    return 1;
    //}
    //dup2(fd, 0);//将fd对应的内容覆盖下标为0的位置对应的内容
    //char buffer[1024];
    //fread(buffer, 1, 1024, stdin);
    //printf("%s", buffer);
    //close(fd);


    //只运行这两句代码：可以正常打印到显示屏，但是如果指令是./myfile > log.txt的话，第一句会打印到文件中，而第二句打印到显示屏上
    //之所以会这样是因为要先进行输出重定向，也就是先打开log.txt，此时它的fd=3，重定向就是把3号描述符的内容覆盖到1号描述符
    //而stdout始终fd=1，stderr始终fd=2，依然是指向显示器，所以第一句打印到文件里面，第二句话打印到显示器
    fprintf(stdout, "hello stdout\n");
    fprintf(stderr, "hello stderr\n");
    //指令为 ./myfile > log.txt 2>&1 ，指的是先重定向到log.txt，再把1号描述符的内容放到2号描述符中，这样2也指向了log.txt
    //也就是说上面的./myfile > log.txt也可以写成 ./myfile 1 > log.txt，就是把log.txt对应文件描述符的内容写到1号描述符

    return 0;
}
